<?php
/**
 * Created By PhpStorm
 * Author: patrick wu
 * Date: 2020/10/29
 * Time: 14:44
 */
namespace App\Service\Live;

use App\Constant\RedisKeyConstant;
use App\Http\Model\Mysql\ProductSpecsModel;
use Carbon\Carbon;
use Illuminate\Support\Facades\Redis;
use App\Http\Model\Mysql\ProductModel;
use App\Http\Model\Mysql\CouponModel;
use Illuminate\Cache;

class OperateService extends BaseService
{
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * set goods recommend
     * @param string $room_name
     * @param $good_id
     * @return mixed
     */
    public function goodsRecommend($room_name, $good_id)
    {
        return Redis::SET(RedisKeyConstant::ROOM_RECOMMEND_PREFIX . $room_name, $good_id);
    }

    /**
     * cancel goods recommend
     * @param $room_name
     * @return mixed
     */
    public function goodsCancelRecommend($room_name)
    {
        return Redis::DEL(RedisKeyConstant::ROOM_RECOMMEND_PREFIX . $room_name);
    }

    /**
     * get recommend goods
     * @param string $room_name
     * @param int $limit
     * @return mixed
     */
    public function getRecommend($room_name = '', $limit = 1)
    {
        return Redis::GET(RedisKeyConstant::ROOM_RECOMMEND_PREFIX . $room_name);
    }

    /**
     * @param string $room_name
     * @param $good_id
     * @return mixed
     */
    public function goodsAdd($room_name, $good_id)
    {
        echo 'Goods Add ' . $room_name . '---' . $good_id . '......' . PHP_EOL;
        Redis::LPUSH(RedisKeyConstant::ROOM_GOOD_SORT_PREFIX . $room_name, $good_id);
        return Redis::SADD(RedisKeyConstant::ROOM_GOOD_LIST_PREFIX . $room_name, $good_id);
    }

    /**
     * @param string $room_name
     * @param $good_id
     * @return mixed
     */
    public function goodsDelete($room_name, $good_id)
    {
        echo 'Goods Delete ' . $room_name . '---' . $good_id . '......' . PHP_EOL;
        Redis::LREM(RedisKeyConstant::ROOM_GOOD_SORT_PREFIX . $room_name, 0, $good_id);
        return Redis::SREM(RedisKeyConstant::ROOM_GOOD_LIST_PREFIX . $room_name, $good_id);
    }

    /**
     * update goods
     * @param string $room_name
     * @param $old_good
     * @param $new_good
     * @return mixed
     */
    public function goodsUpdate($room_name, $old_good, $new_good)
    {
        $good_sort  =   Redis::LRANGE(RedisKeyConstant::ROOM_GOOD_SORT_PREFIX . $room_name, 0, -1);
        foreach ($good_sort as $key => $sort) {
            if ($sort == $old_good) {
                Redis::LSET(RedisKeyConstant::ROOM_GOOD_SORT_PREFIX . $room_name, $key, $new_good);
                break;
            }
        }
        Redis::SREM(RedisKeyConstant::ROOM_GOOD_LIST_PREFIX . $room_name, $old_good);
        return Redis::SADD(RedisKeyConstant::ROOM_GOOD_LIST_PREFIX . $room_name, $new_good);
    }

    /**
     * @param string $room_name
     * @return mixed
     */
    public function goodsGet($room_name = '')
    {
        return Redis::SMEMBERS(RedisKeyConstant::ROOM_GOOD_LIST_PREFIX . $room_name);
    }

    /**
     * @param string $room_name
     * @return mixed
     */
    public function goodsSort($room_name = '')
    {
        return Redis::LRANGE(RedisKeyConstant::ROOM_GOOD_SORT_PREFIX . $room_name, 0, -1);
    }

    /**
     * @param string $good_id
     * @param array $good_price
     * @return mixed
     */
    public function goodsPrice($good_id = '', $good_price = [])
    {
        foreach ($good_price as $key => $item) {
            ProductSpecsModel::where(['id' => $key, 'product_id' => $good_id])->update(['sell_price' => $item]);
        }
    }

    /**
     * @param string $room_name
     * @param string $good_id
     * @param int $move
     * @return bool
     */
    public function goodsMove($room_name = '', $good_id = '', $move = 1)
    {
        $key    =   RedisKeyConstant::ROOM_GOOD_SORT_PREFIX . $room_name;
        $range  =   Redis::LRANGE($key, 0, -1);
        $index  =   NULL;
        foreach ($range as $k => $item) {
            if ($item == $good_id) {
                $index  =   $k;
            }
        }
        if (is_null($index)) {
            return false;
        }

        if ($move == 1) {   //up
            if ($index != 0) {
                Redis::LSET($key, $index, $range[$index - 1]);
                return Redis::LSET($key, $index - 1, $good_id);
            }
        } else {
            if ($index != count($range) - 1) {
                Redis::LSET($key, $index, $range[$index + 1]);
                return Redis::LSET($key, $index + 1, $good_id);
            }
        }

//        Redis::LREM($key, 0, $good_id);

        /**
         * if up or down
         */
        /*if ($move == 1) {       //up
            if (isset($range[$index - 1])) {
                return Redis::LINSERT($key, 'BEFORE', $range[$index - 1], $good_id);
            } else {
                return Redis::LPUSH($key, $good_id);
            }
        } else {
            if (isset($range[$index + 1])) {
                return Redis::LINSERT($key, 'AFTER', ($range[$index + 1] ?? 0) , $good_id);
            } else {
                return Redis::RPUSH($key, $good_id);
            }
        }*/
    }

    /**
     * @param string $room_name
     * @return array|\Illuminate\Support\Collection
     */
    public function goodsInfoSort($room_name = '')
    {
        //goods info
        $goods_data     =   $this->goodsGet($room_name);
        $goods_info     =   $this->goodsInfo($goods_data);
        $goods_sort     =   $this->goodsSort($room_name);
//        $goods_sort     =   array_reverse($goods_sort);
        /**
         * sort in order way
         */
        $new_info   =   [];
        if (empty($goods_sort) || empty($goods_info)) {
            $new_info     =   $goods_info;
        } else {
            foreach ($goods_info as $info) {
                if (($key = array_search($info['id'], $goods_sort)) !== false) {
                    if (isset($new_info[$key])) {
                        $change_info    =   $new_info[$key];
                        $new_info[$key] =   $info;
                        $new_info[]     =   $change_info;
                    } else {
                        $new_info[]     =   $info;
                    }
                } else {
                    $new_info[]     =   $info;
                }
            }
        }
        return $new_info;
    }

    /**
     * @param string $room_name
     * @param $coupon_id
     * @return mixed
     */
    public function couponsAdd($room_name, $coupon_id)
    {
        Redis::LPUSH(RedisKeyConstant::ROOM_COUPON_SORT_PREFIX . $room_name, $coupon_id);
        return Redis::SADD(RedisKeyConstant::ROOM_COUPON_LIST_PREFIX . $room_name, $coupon_id);
    }

    /**
     * @param string $room_name
     * @param $coupon_id
     * @return mixed
     */
    public function couponsDelete($room_name, $coupon_id)
    {
        Redis::LREM(RedisKeyConstant::ROOM_COUPON_SORT_PREFIX . $room_name, 0, $coupon_id);
        return Redis::SREM(RedisKeyConstant::ROOM_COUPON_LIST_PREFIX . $room_name, $coupon_id);
    }

    /**
     * @param string $room_name
     * @param $old_coupon
     * @param $new_coupon
     * @return mixed
     */
    public function couponsUpdate($room_name, $old_coupon, $new_coupon)
    {
        $good_sort  =   Redis::LRANGE(RedisKeyConstant::ROOM_GOOD_SORT_PREFIX . $room_name, 0, -1);
        foreach ($good_sort as $key => $sort) {
            if ($sort == $old_coupon) {
                Redis::LSET(RedisKeyConstant::ROOM_GOOD_SORT_PREFIX . $room_name, $key, $new_coupon);
                break;
            }
        }
        Redis::SREM(RedisKeyConstant::ROOM_COUPON_LIST_PREFIX . $room_name, $old_coupon);
        return Redis::SADD(RedisKeyConstant::ROOM_COUPON_LIST_PREFIX . $room_name, $new_coupon);
    }

    /**
     * @param string $room_name
     * @return mixed
     */
    public function couponsGet($room_name = '')
    {
        return Redis::SMEMBERS(RedisKeyConstant::ROOM_COUPON_LIST_PREFIX . $room_name);
    }

    /**
     * @param string $room_name
     * @return mixed
     */
    public function couponsSort($room_name = '')
    {
        return Redis::LRANGE(RedisKeyConstant::ROOM_COUPON_SORT_PREFIX . $room_name, 0, -1);
    }

    /**
     * sort coupon info
     * @param string $room_name
     * @return array
     */
    public function couponsInfoSort($room_name = '')
    {
        //coupons info
        $coupons_data =   $this->couponsGet($room_name);
        $without_fetch=   $this->couponsInfo($coupons_data);
        $with_fetch   =   [];

        foreach ($without_fetch as $key => $coupon) {
            $with_fetch[$key]   =   $coupon;
            $with_fetch[$key]['fetch']  =   $this->couponsFetch($room_name, $coupon['id']);
        }

        /**
         * sort in order way
         */
        $coupons_sort =   $this->couponsSort($room_name);
        $new_info     =   [];
        if (empty($coupons_sort) || empty($with_fetch)) {
            $new_info     =   $with_fetch;
        } else {
            foreach ($with_fetch as $info) {
                if (($key = array_search($info['id'], $coupons_sort)) !== false) {
                    if (isset($new_info[$key])) {
                        $change_info    =   $new_info[$key];
                        $new_info[$key] =   $info;
                        $new_info[]     =   $change_info;
                    } else {
                        $new_info[] =   $info;
                    }
                } else {
                    $new_info[]     =   $info;
                }
            }
        }
        return $new_info;
    }

    /**
     * get goods info from group shop
     * @param array $goods_array
     * @return array
     */
    public function goodsInfo($goods_array = [])
    {
        if (empty($goods_array)) {
            return [];
        }
        $query_where['is_delete']   =   ProductModel::NOT_DELETE;
        $query_where['is_shelf']    =   ProductModel::IS_SHELF;
        $product_list       =   ProductModel::with([
                                    'specs' =>  function ($query) {
                                        $query->select(['id', 'product_id', 'attr_list', 'sell_price', 'spec_pic', 'sku_code', 'stock']);
                                    },
                                ])->where($query_where)->whereIn('id', $goods_array)->select('id', 'unique_id', 'name', 'sell_price', 'cover_pic', 'stock')->get()->each(function (&$item) {
                                    $spec_desc  =   [];
                                    if (!empty($item->specs)) {
                                        foreach ($item->specs as &$index) {
                                            $attr_list   =   json_decode($index->attr_list, true);
                                            $single_desc =   $single_value  =   [];
                                            foreach ($attr_list as $key => $value) {
                                                $single['name'] =   $key;
                                                $single['value']=   $value;
                                                $single_desc[]  =   $single;
                                                if (isset($spec_desc[$key])) {
                                                    $spec_value =   array_merge(is_array($spec_desc[$key]['value']) ? $spec_desc[$key]['value'] : [$spec_desc[$key]['value']], [$single['value']]);
                                                    $spec_desc[$key]['value']   =   $spec_value;
                                                } else {
                                                    $spec_desc[$key]=   $single;
                                                }
                                                $single_value[] =   $value;
                                            }
                                            $index->attr_list    =   $single_desc;
                                            $index->attr_value   =   $single_value;
                                        }
                                    }
                                    $item->spec_desc  =   array_values(array_map(function (&$item) {
                                        $item['value']  =   is_array($item['value']) ? array_unique($item['value']) : $item['value'];
                                        return $item;
                                    }, $spec_desc));
                                });
        return $product_list->isEmpty() ? [] : $product_list->toArray();
    }

    /**
     * get coupons info from group shop
     * @param array $coupons_array
     * @return array
     */
    public function couponsInfo($coupons_array = [])
    {
        if (empty($coupons_array)) {
            return [];
        }

        $coupon_infos   =   CouponModel::query()->center(CouponModel::NOT_JOIN)->select(['id', 'unique_id', 'name', 'desc', 'picture', 'type', 'scene', 'min_price', 'sub_price', 'discount', 'expire_type', 'expire_day', 'begin_time', 'end_time'])
                            ->orderBy('sorting', 'desc')->get()->each(function (&$item) {
                                $item->begin_time   =   Carbon::createFromTimestamp($item->begin_time)->toDateTimeString();
                                $item->end_time     =   Carbon::createFromTimestamp($item->end_time)->toDateTimeString();
                                //优惠券使用场景说明
                                switch ($item->scene) {
                                    case CouponModel::PLATFORM_COUPON:
                                        $item->scene_desc   =   '平台通用优惠券';
                                        break;

                                    case CouponModel::SHOP_COUPON:
                                        $item->scene_desc   =   '指定店铺优惠券';
                                        break;

                                    case CouponModel::GOOD_COUPON:
                                        $item->scene_desc   =   '指定商品优惠券';
                                        break;

                                    default:
                                        $item->scene_desc   =   '指定商品优惠券';
                                        break;
                                }

                                //优惠券类型说明
                                switch ($item->type) {
                                    case CouponModel::DECREASE_TYPE:
                                        $item->type_desc    =   '满减优惠券';
                                        break;

                                    case CouponModel::DISCOUNT_TYPE:
                                        $item->type_desc    =   '折扣优惠券';
                                        break;

                                    default:
                                        $item->type_desc    =   '满减优惠券';
                                        break;
                                }
                            });

        return $coupon_infos->isEmpty() ? [] : $coupon_infos->toArray();
    }

    /**
     * get coupons fetch count
     * @param string $room_name
     * @param int $coupon_id
     * @return mixed
     */
    public function couponsFetch(string $room_name, int $coupon_id)
    {
        return Redis::SCARD(RedisKeyConstant::COUPON_FETCH_PREFIX . $room_name . '_' . $coupon_id);
    }


    /**
     * client user clickGoods
     * @param string $room_name
     * @param string $goods_id
     * @return mixed
     */
    public function clickGoods($room_name = '', $goods_id = ''){
        return Redis::HINCRBY(RedisKeyConstant::ROOM_CLICK_GOODS_PREFIX . $room_name, $goods_id, 1);
    }

    /**
     * get room total clickGoods
     * @param string $room_name
     * @return float|int
     */
    public function getClickGoods($room_name = '')
    {
        $total_values   =   Redis::HVALS(RedisKeyConstant::ROOM_CLICK_GOODS_PREFIX . $room_name);
        return array_sum($total_values);
    }

}
